﻿using System;

namespace Microsoft.Xna.Framework
{
	/// <summary>
	/// The system window associated with a Game.
	/// </summary>
    public abstract class GameWindow
    {
        #region Private Fields
        string _title;
        #endregion Private Fields

		#region Properties
		/// <summary>
		/// Specifies whether to allow the user to resize the game window.
		/// </summary>
		public abstract bool AllowUserResizing { get; set; }

		/// <summary>
		/// The screen dimensions of the game window's client rectangle.
		/// </summary>
		public abstract Rectangle ClientBounds { get; }

		/// <summary>
		/// Gets the current display orientation, which reflects the physical orientation of the phone in the user's hand.
		/// </summary>
		public abstract DisplayOrientation CurrentOrientation { get; }

		/// <summary>
		/// Gets the handle to the system window.
		/// </summary>
		public abstract IntPtr Handle { get; }

		/// <summary>
		/// Gets the device name of the screen the window is currently in.
		/// </summary>
		public abstract string ScreenDeviceName { get; }

		/// <summary>
		/// Gets and sets the title of the system window.
		/// </summary>
		public string Title
		{
			get { return _title; }
			set
			{
				if (_title != value)
				{
					_title = value;
					SetTitle(_title);
				}
			}
		}
		#endregion

		#region Events
		internal event EventHandler<EventArgs> Activated;

		/// <summary>
		/// Raised when the size of the GameWindow changes.
		/// </summary>
		public event EventHandler<EventArgs> ClientSizeChanged;

		internal event EventHandler<EventArgs> Deactivated;

		/// <summary>
		/// Describes the event raised when the display orientation of the GameWindow changes. When this event occurs, the XNA Framework automatically adjusts the game orientation based on the value specified by the developer with SupportedOrientations.
		/// </summary>
		public event EventHandler<EventArgs> ScreenDeviceNameChanged;

		/// <summary>
		/// Raised when the GameWindow moves to a different display.
		/// </summary>
		public event EventHandler<EventArgs> OrientationChanged;
		#endregion

		#region Constructors
		internal GameWindow()
		{
			this._title = String.Empty;
		}
        #endregion Constructors

		#region Protected Methods
		/// <summary>
		/// Called when the GameWindow gets focus.
		/// </summary>
		protected void OnActivated()
		{
			EventHandler<EventArgs> activatedHandler = this.Activated;
			if (activatedHandler != null)
			{
				activatedHandler(this, EventArgs.Empty);
			}
		}

		/// <summary>
		/// Called when the size of the client window changes. Raises the ClientSizeChanged event.
		/// </summary>
		protected void OnClientSizeChanged()
		{
			EventHandler<EventArgs> clientSizeChangedHandler = this.ClientSizeChanged;
			if (clientSizeChangedHandler != null)
			{
				clientSizeChangedHandler(this, EventArgs.Empty);
			}
		}

		/// <summary>
		/// Called when the GameWindow loses focus.
		/// </summary>
		protected void OnDeactivated()
		{
			EventHandler<EventArgs> deactivatedHandler = this.Deactivated;
			if (deactivatedHandler != null)
			{
				deactivatedHandler(this, EventArgs.Empty);
			}
		}

		/// <summary>
		/// Called when the GameWindow display orientation changes.
		/// </summary>
		protected void OnOrientationChanged()
		{
			EventHandler<EventArgs> orientationChangedHandler = this.OrientationChanged;
			if (orientationChangedHandler != null)
			{
				orientationChangedHandler(this, EventArgs.Empty);
			}
		}

		/// <summary>
		/// Called when the GameWindow needs to be painted.
		/// </summary>
		protected void OnPaint()
		{
		}

		/// <summary>
		/// Called when the GameWindow is moved to a different screen. Raises the ScreenDeviceNameChanged event.
		/// </summary>
		protected void OnScreenDeviceNameChanged()
		{
			EventHandler<EventArgs> screenDeviceNameChangedHandler = this.ScreenDeviceNameChanged;
			if (screenDeviceNameChangedHandler != null)
			{
				screenDeviceNameChangedHandler(this, EventArgs.Empty);
			}
		}

		/// <summary>
		/// Sets the supported display orientations.
		/// </summary>
		/// <param name="orientations">A set of supported display orientations.</param>
		protected internal abstract void SetSupportedOrientations(DisplayOrientation orientations);

		/// <summary>
		/// Sets the title of the GameWindow.
		/// </summary>
		/// <param name="title">The new title of the GameWindow.</param>
		protected abstract void SetTitle(string title);
		#endregion

		#region Public Methods
		/// <summary>
		/// Starts a device transition (windowed to full screen or vice versa).
		/// </summary>
		/// <param name="willBeFullScreen">Specifies whether the device will be in full-screen mode upon completion of the change.</param>
		public abstract void BeginScreenDeviceChange(bool willBeFullScreen);

		/// <summary>
		/// Completes a device transition.
		/// </summary>
		/// <param name="screenDeviceName">The desktop screen to move the window to. This should be the screen device name of the graphics device that has transitioned to full screen.</param>
        public void EndScreenDeviceChange(string screenDeviceName)
        {
			this.EndScreenDeviceChange(screenDeviceName, this.ClientBounds.Width, this.ClientBounds.Height);
        }

		/// <summary>
		/// Completes a device transition.
		/// </summary>
		/// <param name="screenDeviceName">The desktop screen to move the window to. This should be the screen device name of the graphics device that has transitioned to full screen.</param>
		/// <param name="clientWidth">The new width of the game's client window.</param>
		/// <param name="clientHeight">The new height of the game's client window.</param>
        public abstract void EndScreenDeviceChange(string screenDeviceName, int clientWidth, int clientHeight);
		#endregion
    }
}